﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
		<title>Multi Tenancy</title>
		<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
	</head>

	<body>

		<div class="document-contents">

			<h3>What Is Multi Tenancy?</h3>
			<p>
				"<em>Software </em> 
				<strong><em>Multitenancy</em></strong><em> refers to a software 
				</em> <strong><em>architecture</em></strong><em> in which a 
				</em> 
				<strong><em>single instance</em></strong><em> of a software runs on a server and serves 
				</em> 
				<strong><em>multiple tenants</em></strong><em>. 
A tenant is a group of users who share a common access with specific privileges 
to the software instance. With a multitenant architecture, a software application 
is designed to provide every tenant a </em> <strong><em>dedicated share of the instance including 
its data</em></strong><em>, configuration, user management, tenant individual functionality and
 non-functional properties. Multitenancy contrasts with multi-instance architectures,
  where separate software instances operate on behalf of different tenants</em>" 
				(<a href="https://en.wikipedia.org/wiki/Multitenancy">Wikipedia</a>)</p>
			<p>In brief, multi-tenancy is a technique that is used to create <strong>SaaS</strong> (Software as-a Service) 
applications.</p>
			<h4>Database &amp; Deployment Architectures</h4>
			<p>There are some different multi-tenant database &amp; deployment 
			approaches:</p>
			<h5>Multiple Deployment - Multiple Database</h5>
			<p>This is <strong>not multi tenancy</strong> actually. But, if we run <strong>one instance</strong> of 
the application <strong>for each</strong> customer (tenant) with a <strong>
seperated database</strong>, we can serve 
to <strong>multiple tenants</strong> in a single server. We just make sure that multiple instance 
of the application don't <strong>conflict</strong> with each other in same 
server environment.</p>
			<p>This can be possible also for an <strong>existing application</strong> which is not designed 
			as multitenant. It's easier to create such an application since the application has 
not aware of multitenancy. But there are setup, utilization and maintenance 
problems in this approach.</p>
			<h5>Single Deployment - Multiple Database</h5>
			<p>ln this approach, we may run a <strong>single instance</strong> 
			of the application in a server. We have a <strong>master</strong> 
			(host) database to store tenant metadata (like tenant name and 
			subdomain) and a <strong>seperated database</strong> for each 
			tenant. Once we identify the <strong>current tenant</strong> (for 
			example; from subdomain or from a user login form), then we can <strong>switch</strong> to 
			that tenant's database to perform operations.</p>
			<p>In this approach, application should be designed as multi-tenant 
			in some level. But most of the application can remain independed 
			from multi-tenancy. </p>
			<p>We 
should create and maintain a <strong>seperated database</strong> for each tenant, 
			this includes <strong>database migrations</strong>. If we have many 
			customers with dedicated databases, it may take long time to migrate 
			database schema in an application update. Since we have seperated 
			database for a tenant, we can <strong>backup</strong> it's database 
			seperately from other tenants. Also, we can <strong>move</strong> 
			the tenant database to a stronger server if that tenant needs it.</p>
			<h5>Single Deployment - Single Database</h5>
			<p>This is the most <strong>real multi-tenancy</strong> architecture: We only deploy 
				<strong>single 
instance</strong> of the application with a <strong>single database</strong> into a 
				<strong>single server</strong>. We have 
a <strong>TenantId</strong> (or similar) field in each table (for a RDBMS) which 
is used to isolate a tenant's data from others.</p>
			<p>This is easy to setup and maintain. But harder to create such an application. 
Because, we must prevent a Tenant to read or write other tenant data. We may 
add <strong>TenantId filter</strong> for each database read (select) operation. Also, we may 
check it every write, if this entity is related to the <strong>current tenant</strong>. This is 
tedious and error-prone. But ASP.NET Boilerplate helps us here by using <strong>
automatic <a href="Data-Filters.html">data filtering</a></strong>.</p>
			<p>This approach may have performance problems if we have many 
			tenants with huge data. We may use table partitioning or other 
			database features to overcome this problem.</p>
			<h5>Single Deployment - Hybrid Databases</h5>
			<p>We may want to store tenants in single databases normally, but 
			want to create seperated databases for desired tenants. For example, 
			we can store tenants with big data in their own databases, but store 
			all other tenants in a single database.</p>
			<h5>Multiple Deployment - Single/Multiple/Hybrid Database</h5>
			<p>Finally, we may want to deploy our application to more than one 
			server (like web farms) for a better application performance, high 
			availability, and/or scalability. This is independent from the database 
			approach.</p>
			<h3>Multi-Tenancy in ASP.NET Boilerplate</h3>
			<p>ASP.NET Boilerplate can work with all scenarios described above.</p>
			<h4>Enabling Multi Tenancy</h4>
			<p>Multi-tenancy is disabled by default. We can enable it in PreInitialize 
	of our module as shown below:</p>
			<pre lang="cs">Configuration.MultiTenancy.IsEnabled = true;&nbsp;</pre>
			<h4>Host vs Tenant</h4>
			<p>First, we should define two terms used in a multi-tenant system:</p>
			<ul>
				<li>
					<strong>Tenant</strong>: A customer which have it's own users, roles, 
	permissions, settings... and uses the application completely isolated from 
	other tenants. A multi-tenant application will have one or more tenants. If 
	this is a CRM application, different tenants have also thier own accounts, 
	contacts, products and orders. So, when we say a '<strong>tenant user</strong>', we mean a user owned by a tenant.</li>
				<li>
					<strong>Host</strong>: Host is singleton (there is a single host). The 
	Host is responsible to create and manage tenants. So, a '<strong>host user</strong>' is higher level and independent from all 
	tenants and can control they.</li>
			</ul>
			<h4>Session</h4>
			<p>ASP.NET Boilerplate defines <strong>IAbpSession</strong> interface to obtain 
current <strong>user</strong> and <strong>tenant</strong> ids. This interface is 
used in multi-tenancy to get current tenant's id by default. Thus, it can filter data 
based on current tenant's id. We can say these rules: </p>
			<ul>
				<li>If both of UserId and TenantId is null, then current user is <strong>not logged 
	in</strong> to the system. So, we can not know if it's a host user or tenant user. In 
	this case, user can not access to <a href="/Pages/Documents/Authorization">authorized</a> content.</li>
				<li>If UserId is not null and TenantId is null, then we can know that 
	current user is a <strong>host user</strong>.</li>
				<li>If UserId is not null and also TenantId is not null, we can know that 
	current user is a <strong>tenant user</strong>.</li>
				<li>If UserId is null but TenantId is not null, that means we 
				can know the current tenant, but current request is not 
				authorized (user did not login). See the next section to 
				understand how current tenant is determined.</li>
			</ul>
			<p>See <a href="/Pages/Documents/Abp-Session">session documentation</a> for more 
information on the session.</p>
			<h4>Determining Current Tenant</h4>
			<p>Since all tenant users use the same application, we should have a 
			way of distinguishing the tenant of the current request. Default 
			session implementation (ClaimsAbpSession) uses different approaches 
			to find the tenant related to the current request with the given 
			order:</p>
			<ol>
				<li>If user has logged in, then gets TenantId from current 
				claims. Claim name is <em>
				http://www.aspnetboilerplate.com/identity/claims/tenantId </em>
				and should contain an integer value. If it's not found in claims 
				then the user is assumed as a <em>host</em> user.</li>
				<li>If user has not logged in, then it tries to resolve TenantId 
				from <em>tenant resolve contributor</em>s. There are 3 
				pre-defined tenant contributors and runs in given order (first 
				success resolver wins):<ol>
					<li><strong>DomainTenantResolveContributer</strong>: Tries 
					to resolve tenancy name from url, generally from domain or 
					subdomain. You can configure domain format in PreInitialize 
					method of your module (like 
					Configuration.Modules.AbpWebCommon().MultiTenancy.DomainFormat 
					= "{0}.mydomain.com";). If domain format is 
					"{0}.mydomain.com" and current host of the request is <em>
					<strong>acme</strong>.mydomain.com</em>, then tenancy name 
					is resolved as "acme". Then next step is to query 
					ITenantStore to find the TenantId by given tenancy name. If 
					a tenant is found, then it's resolved as the current 
					TenantId.</li>
					<li><strong>HttpHeaderTenantResolveContributer</strong>: 
					Tries to resolve TenantId from "Abp.TenantId" header value, 
					if present (This is a constant defined in 
					Abp.MultiTenancy.MultiTenancyConsts.TenantIdResolveKey).</li>
					<li><strong>HttpCookieTenantResolveContributer</strong>: 
					Tries to resolve TenantId from "Abp.TenantId" cookie value, 
					if present (uses the same constant explained above).</li>
				</ol>
				</li>
			</ol>
			<p>If none of these attemtps can resolve a TenantId, then current 
			requester is considered as the host. Tenant resolvers are 
			extensible. You can add resolvers to <strong>
			Configuration.MultiTenancy.Resolvers</strong> collection, or remove 
			an existing resolver.</p>
			<p>One last thing on resolvers is that; resolved tenant id is cached 
			during the same request for performance reasons. So, resolvers are 
			executed once in a request (and only if current user has not already 
			logged in).</p>
			<h5>Tenant Store</h5>
			<p><strong>DomainTenantResolveContributer </strong>uses ITenantStore 
			to find tenant id by tenancy name. Default implementation of <strong>
			ITenantStore</strong> is <strong>NullTenantStore</strong> which does 
			not contain any tenant and returns null for queries. You can 
			implement and replace it to query tenants from any data source.
			<a href="Zero/Overall.html">Module zero</a> properly implements it 
			to get from it's <a href="Zero/Tenant-Management.html">tenant 
			manager</a>. So, if you are using module zero, don't care about the 
			tenant store.</p>
			<h4>Data Filters</h4>
			<p>For <strong>multi tenant single database</strong> approach, we must add a
			<strong>TenantId</strong> filter to get only current tenant's entities 
			while retrieving <a href="/Pages/Documents/Entities">entities</a> 
			from database. 
ASP.NET Boilerplate automatically does it when you implement one of two 
interfaces for your entity: <strong>IMustHaveTenant</strong> and <strong>IMayHaveTenant</strong>.</p>
			<h5>IMustHaveTenant Interface</h5>
			<p>This interface is used to distinguish entities of different tenants by 
defining <strong>TenantId</strong> property. An example entitiy that implements IMustHaveTenant:</p>
			<pre lang="cs">public class Product : Entity, <strong>IMustHaveTenant</strong>
{
    <strong>public int TenantId { get; set; }</strong>

    public string Name { get; set; }

    //...other properties
}</pre>
			<p>Thus, ASP.NET Boilerplate knows that this is a tenant-specific entity and 
automatically isolates entities of a tenant from other tenants.</p>
			<h5>IMayHaveTenant interface</h5>
			<p>We may need to share an <strong>entity type</strong> between host and tenants. So, an entity 
may be owned by a tenant or the host. IMayHaveTenant interface also defines 
				<strong>TenantId</strong> (similar to IMustHaveTenant), but <strong>nullable</strong> in this case. An example 
entitiy that implements IMayHaveTenant:</p>
			<pre lang="cs">public class Role : Entity, <strong>IMayHaveTenant</strong>
{
    <strong>public int? TenantId { get; set; }</strong>

    public string RoleName { get; set; }

    //...other properties
}</pre>
			<p>We may use same Role class to store Host roles and Tenant roles. In this 
case, TenantId property says if this is an host entity or tenant entitiy. A 
				<strong>null</strong> value means this is a <strong>host</strong> entity, a 
				<strong>non-null</strong> value means this entity owned by a <strong>tenant</strong> which's Id is the 
				<strong>TenantId</strong>.</p>
			<h5>Additional Notes</h5>
			<p>IMayHaveTenant is not common as IMustHaveTenant. For example, a Product class 
can not be IMayHaveTenant since a Product is related to actual application 
functionality, not related to managing tenants. So, use IMayHaveTenant interface 
carefully since it's harder to maintain a code shared by host and tenants.</p>
			<p>When you define an entity type as IMustHaveTenant or 
			IMayHaveTenant, <strong>always set TenantId</strong> when you create 
			a new entity (While ASP.NET Boilerplate tries to set it from current 
			TenantId, it may not be possible in some cases, especially for 
			IMayHaveTenant entities). Most of times, this will be the only point 
			you deal with TenantId properties. You don't need to explicitly 
			write TenantId filter in Where conditions while writing LINQ, since 
			it will be automatically filtered.</p>
			<h4>Switching Between Host and Tenants</h4>
			<p>While working on a multitenant application database, we should 
			know the <strong>current tenant</strong>. By default, it's obtained 
			from <a href="Abp-Session.html">IAbpSession</a> (as described 
			before). We can change this behaviour and switch to other tenant's 
			database. Example:</p>
			<pre lang="cs">public class ProductService : ITransientDependency
{
    private readonly IRepository&lt;Product&gt; _productRepository;
    private readonly IUnitOfWorkManager _unitOfWorkManager;

    public ProductService(IRepository&lt;Product&gt; productRepository, <strong>IUnitOfWorkManager unitOfWorkManager</strong>)
    {
        _productRepository = productRepository;
        _unitOfWorkManager = unitOfWorkManager;
    }

    [UnitOfWork]
    public virtual List&lt;Product&gt; GetProducts(int tenantId)
    {
        using (<strong>_unitOfWorkManager.Current.SetTenantId(tenantId)</strong>)
        {
            return _productRepository.GetAllList();
        }
    }
}</pre>
			<p>SetTenantId ensures that we are working on given tenant data, 
			independent from database architecture:</p>
			<ul>
				<li>If given tenant has a dedicated database, it switches to 
				that database and gets products from it.</li>
				<li>If given tenant has not a dedicated database (single 
				database approach, for example), it adds automatic TenantId 
				filter to query get only that tenant's products.</li>
			</ul>
			<p>If we don't use SetTenantId, it gets tenantId from
			<a href="Abp-Session.html">session</a>, as said before. There are 
			some notes and best practices here:</p>
			<ul>
				<li>Use <strong>SetTenantId(null)</strong> to switch to the 
				host.</li>
				<li>Use SetTenantId within a <strong>using</strong> block as in 
				the example if there is not a special case. Thus, it 
				automatically restore tenantId at the end of the using block and the code calls GetProducts method works as before.</li>
				<li>You can use SetTenantId in <strong>nested blocks </strong>if 
				it's needed.</li>
				<li>Since <strong>_unitOfWorkManager.Current</strong> only 
				available in a <a href="Unit-Of-Work.html">unit of work</a>, be 
				sure that your code runs in a UOW.</li>
			</ul>

		</div>

	</body>

</html>
